package ar.edu.itba.pod.printer.impl;


import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import ar.edu.itba.pod.printer.Document;
import ar.edu.itba.pod.printer.PrinterDispatcher;

public class EnhancedPoolPrinterDispatcher implements PrinterDispatcher{
	
	private Queue<Document> queue= new LinkedList<Document>();
	private List<ThreadPrinter> printersPool = new LinkedList<ThreadPrinter>();
	private final int MAX_PRINTERS = 20;
	private volatile int currentPrinters;
	
	
	private MyThread mainThread = new MyThread() {
		
		@Override
		public void excecute() {
			printIfNotEmpty();
		}
	};
	
	public EnhancedPoolPrinterDispatcher(int printers) {
		for(int i=1;i<=printers;i++){
			ThreadPrinter thp=new ThreadPrinter("P"+i);
			printersPool.add(thp);
			currentPrinters++;
			thp.start();
		}
		mainThread.start();
	}
	
	@Override
	public void printDocument(Document document) {
		queue.add(document);
	}

	@Override
	public void finishPrintRequests() {
		for(ThreadPrinter thp: printersPool){
			thp.finish();
		}
		mainThread.finish();
//		printIfNotEmpty();
	}
	
	public void addPrinter(){
		if(printersPool.size() < MAX_PRINTERS){
			ThreadPrinter thp=new ThreadPrinter("P"+(printersPool.size() + 1));
			printersPool.add(thp);
			currentPrinters++;
			thp.start();
			System.out.print("[" + thp.getName() + "]");
		} 
	}
	
	public void removePrinter(){
		if(printersPool.size()>0){
			ThreadPrinter thp= printersPool.get(0);
			printersPool.remove(thp);
			currentPrinters--;
			thp.finish();
			System.out.print("[-" + thp.getName() + "]");
		}
	}
	
	private void printIfNotEmpty(){
		if(!queue.isEmpty()){
			ThreadPrinter thp=FindFirstPrinterInactive();
			thp.addJob(queue.poll());
		}
	}

	private ThreadPrinter FindFirstPrinterInactive(){
		boolean founded=false;
		ThreadPrinter thp = null;
		
		while(!founded){
			for(int i=0; !founded && i<currentPrinters;i++){
				if(!printersPool.get(i).isBusy()){
					thp=printersPool.get(i);
					founded=true;
				}
			}
		}
		return thp;
	}
}
